/***********************************
 * Jonathan Woolery & Ricardo Tijero
 * CPE453 - Winter 2013
 * F.Khosmood
 * Project #4 --TINY FS
 * ******************************/

#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>

#define MAGIC_LOC 1
#define MAGIC_NUM 0x45
#define SUPERBLOCK 0x01
#define INODE 0x02
#define FILE_EXTENT 0x03
#define FREE 0x04
#define SUPER_LOC 0
#define FREE_VECT_LOC 4
#define DATA_SIZE 252
#define INODE_META 12
#define BLOCK_META 4
#define RW 0
#define RO 1

#define blockSize 256   /* Block Size in Bytes */
#define defaultDiskName "tinyFSDISK"
#define defaultDiskSize 102400  /* Disk Size in Bytes */

#define MAX_BLOCKS 40

#define FILE_NAME_SIZE 8
#define MAGIC_NUM 0x45


/* How to implement blocks?
 * 1. superblock is always first block in disk. at array position 0
 * 1.a. superblock contains magic number, block # of root inode, free-list implementation, and other info
 * 2. inode block contains name of file, file block list implementation (one for each file on disk)
 * 3. file extents contains block# of the inode block for the file the extent belongs to
 * 4. free block
 *
 *
 * Block format
 * byte 0 == block type  // since block type is defined here,
 *                          if we use structs, can use same basic struct for all blocks
 *                          and identify by block type characteristic
 * byte 2 == 0x45 magic number
 * */

typedef struct File_Object{
    char filename[9];
    int fp;
    int block;
    unsigned int size;
    int mode;
    struct File_Object *next;
}FileObj;

FileObj openFileTable[39];


typedef int fileDescriptor;

/* required functions for tiny FS */
fileDescriptor tfs_openFile(char *name);
int tfs_closeFile(fileDescriptor FD);
int tfs_writeFile(fileDescriptor FD, char *buffer);
int tfs_deleteFile(fileDescriptor FD);
int tfs_readByte(fileDescriptor FD, char *buffer);
int tfs_seek(fileDescriptor FD, int offset);

/* Additional areas of functionality*/
int tfs_rename(char *oldName, char *newName);
int tfs_dir();

int tfs_makeRO(char *name);
int tfs_makeRW(char *name);
/* tfs write byte --> writes to current location of file pointer */
int tfs_writeByte(fileDescriptor FD, unsigned char data);

/* helper functions */
int tfs_writeMode(char *name, char mode);
FileObj *getFileEntry(FileObj *head, int block);
int nextFreeBlk();
int totalFreeBlks();
int populateBlockStateArr(int disk);
int populateFileList(int disk);
int writeVector();
void unpackBits(unsigned byte, char bits[], int *pos);
void splitInt(unsigned int num, unsigned char *a);
int mergeInt(unsigned char *arr);
FileObj *newFileObj(char *fileName, int blockNum, unsigned int fileSize, int mode);
void freeList(FileObj *obj);
void freeChain(int block);
